#include "Typedef.h"
#include "eeprom_driver.h"
#include "eeprom_bsp.h"


struct EEPROM_BSP_S
{
	u32 write_addr;
	EEPORM_DATA* DD;
};

static EEPORM_DATA  eeprom_image;//eeprom 数据的镜像数据
static struct EEPROM_BSP_S eeprom_bsp={.write_addr=0};


static u32 eeprom_data_sum_get(EEPORM_DATA * data)
{
	u32 * buff = (u32*)(data->buff+4);
	u8 length = (EEPROM_PAGE_SIZE>>2) - 1;
	eeprom_crc_calcblock(buff,length);
	return eeprom_crc_calcblock(buff,length);
}

void eeprom_data_crc_set(EEPORM_DATA * data)
{
	data->D.crc = eeprom_data_sum_get(data);
}

// 每page中的数据分为：擦除后数据, 正常数据，异常数据(小概率事件)
//该函数执行完成后，eeprom块全为擦除后数据
static void eeprom_get_init_address(void)
{
	EEPORM_DATA data;
	int i=0;
	u8 data_flag[EEPROM_PAGE_NUM]={0};

	for(i=0; i<EEPROM_PAGE_NUM; i++)
	{
		if(eeprom_page_erase_ok(i*EEPROM_PAGE_SIZE))
			data_flag[i] = 1;//当前page是擦除后数据
		else
		{
			eeprom_read(i*EEPROM_PAGE_SIZE,data.buff);
			if(data.D.crc == eeprom_data_sum_get(&data))
				data_flag[i] = 0;//当前page是正常数据
			else
				data_flag[i] =2;//当前page是异常数据,小概率事件
		}
	}

	for(i=0; i<EEPROM_PAGE_NUM; i++)
	{
		if((0 == data_flag[i]) && (1 == data_flag[(i+1)%EEPROM_PAGE_NUM]))//找到上次断电的数据位置
		{
			eeprom_read(i*EEPROM_PAGE_SIZE,eeprom_image.buff);
			for(int i=0; i<EEPROM_PAGE_SIZE; i++)
				eeprom_bsp.DD->buff[i] = eeprom_image.buff[i];
			eeprom_bsp.write_addr = ((i+1)%EEPROM_PAGE_NUM)*EEPROM_PAGE_SIZE;
		}
		else if((1 != data_flag[i]))//不等于擦除后数据 就擦除
		{
			eeprom_erase(i*EEPROM_PAGE_SIZE);
			eeprom_read(i*EEPROM_PAGE_SIZE,data.buff);
		}
	}
}

void eeprom_bsp_init(EEPORM_DATA* const data)
{
	eeprom_bsp.write_addr = 0;
	eeprom_bsp.DD = data;
	eeprom_data_crc_set(eeprom_bsp.DD);//防止task层，未进行crc计算
	for(int i=0; i<EEPROM_PAGE_SIZE; i++)
		eeprom_image.buff[i] = eeprom_bsp.DD->buff[i];
	eeporm_init();
	eeprom_get_init_address();
}

int eeporm_bsp_save_data(void)
{
	int i=0;
	eeprom_data_crc_set(eeprom_bsp.DD);//防止task层，未进行crc计算
	for(i=0; i<EEPROM_PAGE_SIZE; i++)
	{
		if(eeprom_bsp.DD->buff[i] != eeprom_image.buff[i])
			break ;
	}
	if(i >= EEPROM_PAGE_SIZE)
		return 0;

	eeprom_write( eeprom_bsp.write_addr, eeprom_bsp.DD->buff);
	eeprom_read( eeprom_bsp.write_addr,eeprom_image.buff);

	eeprom_bsp.write_addr += EEPROM_PAGE_SIZE;//不管成功失败，继续写下一块
	eeprom_bsp.write_addr %= EEPROM_SIZE;

	if(0 == eeprom_page_erase_ok(eeprom_bsp.write_addr))
		eeprom_erase(eeprom_bsp.write_addr);

	for(i=0; i<EEPROM_PAGE_SIZE; i++)
	{
		if(eeprom_bsp.DD->buff[i] != eeprom_image.buff[i])
			break;
	}
	if(i<EEPROM_PAGE_SIZE)//wirte failed!!
	{
		for(int j=0; j<EEPROM_PAGE_SIZE; j++)//恢复数据
			eeprom_image.buff[j] = eeprom_bsp.DD->buff[j];
		return -1;
	}
	return 0;
}

